package com.skynet.supervision.utils;

import lombok.val;
import org.slf4j.helpers.MessageFormatter;

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Stream;

public class Strings extends org.apache.commons.lang3.StringUtils{

    public static final String BLANK = "";

    /**
     * 下划线
     */
    private static final char SEPARATOR = '_';


    public static boolean strcmp(String l, String r) {
        if (l == null && r == null) {
            return true;
        }
        if (l == null || r == null) {
            return false;
        }
        return l.equals(r);
    }

    public static boolean strcmp(String l, String r, boolean ignoreCase) {
        if (l == null && r == null) {
            return true;
        }
        if (l == null || r == null) {
            return false;
        }
        return l.equalsIgnoreCase(r);
    }

    /**
     * format string like slf4j
     *
     * @param format string format,like slf4j, "{} {}"
     * @param args   any object params
     * @return String
     */
    public static @NotNull String sprintf(String format, Object... args) {
        return MessageFormatter.arrayFormat(format, args).getMessage();
    }

    public static @NotNull boolean notEmpty(String target) {
        return target != null && !target.isEmpty();
    }

    public static @NotNull boolean isEmpty(String target) {
        return !notEmpty(target);
    }

    public static @NotNull String filedNameToSetterName(@NotNull Field field) {
        return filedNameToSetterName(field.getName(), field.getType());
    }

    public static @NotNull String filedNameToSetterName(@NotEmpty String fieldName, @NotNull Class<?> fieldType) {
        val fieldNameCharArr = fieldName.toCharArray();
        char fl = fieldNameCharArr[0];
        if (fl >= 97 && fl <= 122) {
            fl -= 32;
            fieldNameCharArr[0] = fl;
        }
        fieldName = String.valueOf(fieldNameCharArr);
        //
        val prefix = "set";
        return Strings.sprintf("{}{}", prefix, fieldName);
    }

    public static @NotNull String filedNameToGetterName(@NotNull Field field) {
        return filedNameToGetterName(field.getName(), field.getType());
    }

    public static @NotNull String filedNameToGetterName(@NotEmpty String fieldName, @NotNull Class<?> fieldType) {
        val fieldNameCharArr = fieldName.toCharArray();
        char fl = fieldNameCharArr[0];
        if (fl >= 97 && fl <= 122) {
            fl -= 32;
            fieldNameCharArr[0] = fl;
        }
        fieldName = String.valueOf(fieldNameCharArr);
        // lombok 生成布尔型getter的规则:
        // boolean 前缀为 is
        // Boolean 前缀为 get
        var prefix = "get";
        if (fieldType == boolean.class) {
            prefix = "is";
        }
        return Strings.sprintf("{}{}", prefix, fieldName);
    }

    /**
     * 左侧padding
     *
     * @param src 源
     * @param len 总长度
     * @param ch  填充的字符
     */
    public static String padLeft(String src, int len, char ch) {
        int pad = len - src.length();
        if (pad <= 0) {
            return src;
        }
        val sb = new StringBuilder(len);
        Stream.generate(() -> ch)
                .limit(pad)
                .forEach(sb::append);
        sb.append(src);
        return sb.toString();
    }

    /**
     * 右侧padding
     *
     * @param src 源
     * @param len 总长度
     * @param ch  填充的字符
     */
    public static String padRight(String src, int len, char ch) {
        int pad = len - src.length();
        if (pad <= 0) {
            return src;
        }
        val sb = new StringBuilder(src);
        Stream.generate(() -> ch)
                .limit(pad)
                .forEach(sb::append);
        return sb.toString();
    }

    /**
     * 去空格
     */
    public static String trim(String str) {
        return (str == null ? "" : str.trim());
    }

    /**
     * 截取字符串
     *
     * @param str   字符串
     * @param start 开始
     * @return 结果
     */
    public static String substring(final String str, int start) {
        if (str == null) {
            return BLANK;
        }

        if (start < 0) {
            start = str.length() + start;
        }

        if (start < 0) {
            start = 0;
        }
        if (start > str.length()) {
            return BLANK;
        }

        return str.substring(start);
    }

    /**
     * 截取字符串
     *
     * @param str   字符串
     * @param start 开始
     * @param end   结束
     * @return 结果
     */
    public static String substring(final String str, int start, int end) {
        if (str == null) {
            return BLANK;
        }

        if (end < 0) {
            end = str.length() + end;
        }
        if (start < 0) {
            start = str.length() + start;
        }

        if (end > str.length()) {
            end = str.length();
        }

        if (start > end) {
            return BLANK;
        }

        if (start < 0) {
            start = 0;
        }
        if (end < 0) {
            end = 0;
        }

        return str.substring(start, end);
    }

    /**
     * 字符串转set
     *
     * @param str 字符串
     * @param sep 分隔符
     * @return set集合
     */
    public static final Set<String> str2Set(String str, String sep) {
        return new HashSet<String>(str2List(str, sep, true, false));
    }

    /**
     * 字符串转list
     *
     * @param str         字符串
     * @param sep         分隔符
     * @param filterBlank 过滤纯空白
     * @param trim        去掉首尾空白
     * @return list集合
     */
    public static final List<String> str2List(String str, String sep, boolean filterBlank, boolean trim) {
        List<String> list = new ArrayList<String>();
        if (Strings.isEmpty(str)) {
            return list;
        }

        // 过滤空白字符串
        if (filterBlank && Strings.isEmpty(str)) {
            return list;
        }
        String[] split = str.split(sep);
        for (String string : split) {
            if (filterBlank && Strings.isEmpty(string)) {
                continue;
            }
            if (trim) {
                string = string.trim();
            }
            list.add(string);
        }

        return list;
    }
}
